package com.maning.mnvideoplayerlibrary.player;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.maning.mnvideoplayerlibrary.R;
import com.maning.mnvideoplayerlibrary.utils.PlayerUtils;
import com.maning.mnvideoplayerlibrary.view.ProgressWheel;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;


/**
 * 播放器
 *
 * @author wzy
 */
public class YLVideoPlayer extends FrameLayout implements View.OnClickListener, SeekBar.OnSeekBarChangeListener,
        SurfaceHolder.Callback, MediaPlayer.OnCompletionListener,
        MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener {

    private static final String TAG = "YLVideoPlayer";
    private Context context;
    private Activity activity;

    static final Handler myHandler = new Handler(Looper.getMainLooper());

    //  SurfaceView的创建比较耗时！！！！！
    private SurfaceHolder surfaceHolder;
    private MediaPlayer mediaPlayer;

    private String videoPath;
    private String videoPlaceholder;    //  视频第一帧占位图（封面）
    private int videoPosition = 0;

    //  控件的位置信息
    private float mediaPlayerX;
    private float mediaPlayerY;

    //  计时器
    private Timer timerVideoTime;
    private TimerTask taskVideoTimer;
    private Timer timerController;
    private TimerTask taskController;

    private boolean isPrepare = false;
    private boolean isFirstPlay = false;

    private SurfaceView playerSurfaceView;
    private ImageView ivFirstFrame;
    private ImageView ivPlayPause;
    private TextView tvTime;    //  播放时间    当前时间/总时间
    private SeekBar seekBar;
    private RelativeLayout playerRlProgress;
    private LinearLayout playerError;
    private LinearLayout playerNet;
    private ProgressWheel playerProgressBar;
    private ImageView playerIvPlayCenter;

    public YLVideoPlayer(Context context) {
        this(context, null);
    }

    public YLVideoPlayer(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public YLVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        activity = (Activity) this.context;
        init();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        int screenWidth = PlayerUtils.getScreenWidth(activity);
        int screenHeight = PlayerUtils.getScreenHeight(activity);
        ViewGroup.LayoutParams layoutParams = getLayoutParams();

        //  newConfig.orientation获得当前屏幕状态是横向或者竖向
        //  Configuration.ORIENTATION_PORTRAIT 表示竖向
        //  Configuration.ORIENTATION_LANDSCAPE 表示横屏
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            //  计算视频的大小16：9
            layoutParams.width = screenWidth;
            layoutParams.height = screenWidth * 9 / 16;

            setX(mediaPlayerX);
            setY(mediaPlayerY);
        }
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            layoutParams.width = screenWidth;
            layoutParams.height = screenHeight;

            setX(0);
            setY(0);
        }
        setLayoutParams(layoutParams);
    }

    private void init() {

        isFirstPlay = false;

        View inflate = View.inflate(context, R.layout.yl_player_view, this);
        ivFirstFrame = (ImageView) inflate.findViewById(R.id.yl_iv_first_frame);
        playerSurfaceView = (SurfaceView) inflate.findViewById(R.id.yl_player_surfaceView);

        ivPlayPause = (ImageView) inflate.findViewById(R.id.yl_iv_play_pause);
        tvTime = (TextView) inflate.findViewById(R.id.yl_tv_time);
        seekBar = (SeekBar) inflate.findViewById(R.id.yl_seekBar);
        playerRlProgress = (RelativeLayout) inflate.findViewById(R.id.yl_player_rl_progress);
        playerError = (LinearLayout) inflate.findViewById(R.id.yl_player_ll_error);
        playerNet = (LinearLayout) inflate.findViewById(R.id.yl_player_ll_net);
        playerProgressBar = (ProgressWheel) inflate.findViewById(R.id.yl_player_progressBar);
        playerIvPlayCenter = (ImageView) inflate.findViewById(R.id.yl_player_iv_play_center);

        seekBar.setOnSeekBarChangeListener(this);
        ivPlayPause.setOnClickListener(this);
        playerError.setOnClickListener(this);
        playerNet.setOnClickListener(this);
        playerIvPlayCenter.setOnClickListener(this);

        playerSurfaceView.setOnClickListener(this);

        //初始化
        initViews();

        if (!isFirstPlay)   //  不是第一次播放
        {
            playerIvPlayCenter.setVisibility(View.VISIBLE);
            playerProgressBar.setVisibility(View.GONE);
        }

        initSurfaceView();

        myHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mediaPlayerX = getX();
                mediaPlayerY = getY();
                Log.i(TAG, "控件的位置---X：" + mediaPlayerX + "，Y：" + mediaPlayerY);
            }
        }, 1000L);
    }

    private void initViews() {
        ivPlayPause.setVisibility(View.GONE);
        seekBar.setVisibility(View.GONE);

        playerRlProgress.setVisibility(View.VISIBLE);
        playerProgressBar.setVisibility(View.VISIBLE);
        playerError.setVisibility(View.GONE);
        playerNet.setVisibility(View.GONE);
        playerIvPlayCenter.setVisibility(View.GONE);
    }

    private void initSurfaceView() {
        Log.i(TAG, "initSurfaceView");
        // 得到SurfaceView容器，播放的内容就是显示在这个容器里面
        surfaceHolder = playerSurfaceView.getHolder();
        surfaceHolder.setKeepScreenOn(true);
        // SurfaceView的一个回调方法
        surfaceHolder.addCallback(this);
    }

    @Override
    public void onClick(View v) {
        int i = v.getId();
        if (i == R.id.yl_iv_play_pause) //  播放按钮
        {
            if (mediaPlayer != null)    //  判空
            {
                if (mediaPlayer.isPlaying())    //  正在播放
                {
                    mediaPlayer.pause();
                    ivPlayPause.setImageResource(R.drawable.yl_player_play);
                } else  //  已暂停播放
                {
                    mediaPlayer.start();
                    ivPlayPause.setImageResource(R.drawable.yl_player_pause);
                }
            }
        } else if (i == R.id.yl_player_surfaceView)     //  控制进度条及播放暂停 是否显示
        {
            if (isPrepare) initBottomMenuState();

        } else if (i == R.id.yl_player_ll_error || i == R.id.yl_player_ll_net || i == R.id.yl_player_iv_play_center)    //  异常情况 错误 无网 开始
        {
            playVideo(videoPath, 0);
        }
    }

    //--------------------------------------------------------------------------------------
    // ######## 相关View的操作 ########
    //--------------------------------------------------------------------------------------

    //  下面菜单的显示和隐藏
    private void initBottomMenuState() {
        if (ivPlayPause.getVisibility() == View.GONE) {
            initControllerTask();
            ivPlayPause.setVisibility(VISIBLE);
            seekBar.setVisibility(VISIBLE);
        } else {
            destroyControllerTask(true);
        }
    }

    private void dismissControllerMenu() {
        playerIvPlayCenter.setVisibility(GONE);
        ivPlayPause.setVisibility(GONE);
        seekBar.setVisibility(GONE);
    }

    private void showErrorView() {
        playerIvPlayCenter.setVisibility(View.GONE);
        playerNet.setVisibility(View.GONE);
        playerProgressBar.setVisibility(View.GONE);
        playerError.setVisibility(View.VISIBLE);
    }

    private void showNoNetView() {
        playerIvPlayCenter.setVisibility(View.GONE);
        playerNet.setVisibility(View.VISIBLE);
        playerProgressBar.setVisibility(View.GONE);
        playerError.setVisibility(View.GONE);
    }

//--------------------------------------------------------------------------------------
    // ######## 计时器相关操作 ########
    //--------------------------------------------------------------------------------------

    private void initTimeTask() {
        timerVideoTime = new Timer();
        taskVideoTimer = new TimerTask() {
            @Override
            public void run() {
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mediaPlayer == null) {
                            return;
                        }
                        //设置时间
                        tvTime.setText(String.valueOf(PlayerUtils.converLongTimeToStr(mediaPlayer.getCurrentPosition()) + "/" + PlayerUtils.converLongTimeToStr(mediaPlayer.getDuration())));
                        //进度条
                        int progress = mediaPlayer.getCurrentPosition();
                        seekBar.setProgress(progress);
                    }
                });
            }
        };
        timerVideoTime.schedule(taskVideoTimer, 0, 1000);
    }

    private void destroyTimeTask() {
        if (timerVideoTime != null && taskVideoTimer != null) {
            timerVideoTime.cancel();
            taskVideoTimer.cancel();
            timerVideoTime = null;
            taskVideoTimer = null;
        }
    }

    private void initControllerTask() {
        // 设置计时器,控制器的影藏和显示
        timerController = new Timer();
        taskController = new TimerTask() {
            @Override
            public void run() {
                destroyControllerTask(false);
            }
        };
        timerController.schedule(taskController, 5000);
        initTimeTask();
    }

    private void destroyControllerTask(boolean isMainThread) {
        if (isMainThread) {
            dismissControllerMenu();
        } else {
            myHandler.post(new Runnable() {
                @Override
                public void run() {
                    dismissControllerMenu();
                }
            });
        }
        if (timerController != null && taskController != null) {
            timerController.cancel();
            taskController.cancel();
            timerController = null;
            taskController = null;
        }
        destroyTimeTask();
    }

    //--------------------------------------------------------------------------------------
    // ######## 接口方法实现 ########
    //--------------------------------------------------------------------------------------
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            int maxCanSeekTo = seekBar.getMax() - 5 * 1000;
            if (seekBar.getProgress() < maxCanSeekTo) {
                mediaPlayer.seekTo(seekBar.getProgress());
            } else {
                //不能拖到最后
                mediaPlayer.seekTo(maxCanSeekTo);
            }
        }
    }

    //  播放
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.setDisplay(holder); //  添加到容器中
        //  播放完成的监听
        mediaPlayer.setOnCompletionListener(this);
        //  异步准备的一个监听函数，准备好了就调用里面的方法
        mediaPlayer.setOnPreparedListener(this);
        //  播放错误的监听
        mediaPlayer.setOnErrorListener(this);
        mediaPlayer.setOnBufferingUpdateListener(this);

        if (!TextUtils.isEmpty(videoPlaceholder))   //  封面不为空时加载
        {

            Glide.with(getContext())
                    .load(videoPlaceholder)
                    .into(ivFirstFrame);
            ivFirstFrame.setVisibility(VISIBLE);
        }

        if (isFirstPlay)    //  第一次初始化需不需要主动播放
        {
            if (!PlayerUtils.isNetworkConnected(context) && videoPath.startsWith("http"))   //  判断当前有没有网络（播放的是网络视频）
            {
                Toast.makeText(context, context.getString(R.string.ylPlayerNoNetHint), Toast.LENGTH_SHORT).show();
                showNoNetView();
            } else  //  有网
            {

                if (PlayerUtils.isMobileConnected(context))  // 手机网络给提醒
                {
                    Toast.makeText(context, context.getString(R.string.ylPlayerMobileNetHint), Toast.LENGTH_SHORT).show();
                }
                //  添加播放路径
                try {
                    mediaPlayer.setDataSource(videoPath);
                    // 准备开始,异步准备，自动在子线程中
                    mediaPlayer.prepareAsync();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        isFirstPlay = true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

        if (mediaPlayer != null)     //  保存播放位置
        {
            videoPosition = mediaPlayer.getCurrentPosition();
        }
        destroyControllerTask(true);
        pauseVideo();
        Log.i(TAG, "surfaceDestroyed---videoPosition：" + videoPosition);
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        ivPlayPause.setImageResource(R.drawable.yl_player_play);
        destroyControllerTask(true);
        videoPosition = 0;
        if (onCompletionListener != null) {
            onCompletionListener.onCompletion(mediaPlayer);
        }
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        Log.i(TAG, "二级缓存onBufferingUpdate: " + percent);
        if (percent >= 0 && percent <= 100) {
            int secondProgress = mp.getDuration() * percent / 100;
            seekBar.setSecondaryProgress(secondProgress);
        }
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "发生错误error:" + what);
        if (what != -38) {  //这个错误不管
            showErrorView();
        }
        return true;
    }

    @Override
    public void onPrepared(final MediaPlayer mediaPlayer) {

        if (!mediaPlayer.isPlaying())   //  没有播放时
        {
            mediaPlayer.start(); // 开始播放
        }
        isPrepare = true;
        if (videoPosition > 0) {
            Log.i(TAG, "onPrepared---videoPosition:" + videoPosition);
            mediaPlayer.seekTo(videoPosition);
            videoPosition = 0;
        }
        // 把得到的总长度和进度条的匹配
        seekBar.setMax(mediaPlayer.getDuration());
        ivPlayPause.setImageResource(R.drawable.yl_player_pause);
        tvTime.setText(String.valueOf(PlayerUtils.converLongTimeToStr(mediaPlayer.getCurrentPosition()) + "/" + PlayerUtils.converLongTimeToStr(mediaPlayer.getDuration())));
        //延时：避免出现上一个视频的画面闪屏
        myHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                initBottomMenuState();
                playerRlProgress.setVisibility(View.GONE);
            }
        }, 500);
    }

    //--------------------------------------------------------------------------------------
    // ######## 对外提供的方法 ########
    //--------------------------------------------------------------------------------------

    /**
     * 设置视频信息
     *
     * @param url 视频地址
     */
    public void setDataSource(String url, String placeholder) {
        this.videoPath = url;
        this.videoPlaceholder = placeholder;
    }

    /**
     * 播放视频
     *
     * @param url 视频地址
     */
    public void playVideo(String url) {
        playVideo(url, videoPosition);
    }

    /**
     * 播放视频（支持上次播放位置）
     * 自己记录上一次播放的位置，然后传递position进来就可以了
     *
     * @param url      视频地址
     * @param position 视频跳转的位置
     */
    public void playVideo(String url, int position) {
        //地址判空处理
        if (TextUtils.isEmpty(url)) {
            Toast.makeText(context, context.getString(R.string.ylPlayerUrlEmptyHint), Toast.LENGTH_SHORT).show();
            return;
        }
        //  销毁ControllerView
        destroyControllerTask(true);

        //  赋值
        videoPath = url;
        videoPosition = position;
        isPrepare = false;

        //  判断当前有没有网络（播放的是网络视频）
        if (!PlayerUtils.isNetworkConnected(context) && url.startsWith("http")) {
            Toast.makeText(context, context.getString(R.string.ylPlayerNoNetHint), Toast.LENGTH_SHORT).show();
            showNoNetView();
            return;
        }

        if (PlayerUtils.isMobileConnected(context)) //  手机网络给提醒
        {
            Toast.makeText(context, context.getString(R.string.ylPlayerMobileNetHint), Toast.LENGTH_SHORT).show();
        }

        //  重置MediaPlayer
        resetMediaPlayer();

        if (0 == videoPosition && ivFirstFrame.getVisibility() == VISIBLE)  //  清除封面图片
        {
            ivFirstFrame.setVisibility(GONE);
        }
        //  初始化View
        initViews();
    }

    private void resetMediaPlayer() {
        try {
            if (mediaPlayer != null) {
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.pause();
                    mediaPlayer.stop();
                }
                //  重置mediaPlayer
                mediaPlayer.reset();
                //  添加播放路径
                mediaPlayer.setDataSource(videoPath);
                //  准备开始,异步准备，自动在子线程中
                mediaPlayer.prepareAsync();
            } else {
                Toast.makeText(context, "播放器初始化失败", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 播放视频
     */
    public void startVideo() {
        if (mediaPlayer != null) {
            mediaPlayer.start();
            ivPlayPause.setImageResource(R.drawable.yl_player_pause);
        }
        ivFirstFrame.setVisibility(GONE);
    }

    /**
     * 暂停视频
     */
    public void pauseVideo() {
        if (videoPosition > 0)    //  播放过视频才取消预览图
        {
            ivFirstFrame.setVisibility(GONE);
        }

        if (mediaPlayer != null)    //  判空
        {
            mediaPlayer.pause();
            ivPlayPause.setImageResource(R.drawable.yl_player_play);
            videoPosition = mediaPlayer.getCurrentPosition();
        }

    }

    /**
     * 获取当前播放的位置
     */
    public int getVideoCurrentPosition() {
        int position = 0;
        if (mediaPlayer != null) {
            position = mediaPlayer.getCurrentPosition();
        }
        return position;
    }

    /**
     * 获取视频总长度
     */
    public int getVideoTotalDuration() {
        int position = 0;
        if (mediaPlayer != null) {
            position = mediaPlayer.getDuration();
        }
        return position;
    }

    /**
     * 获取管理者
     */
    public MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    /**
     * 销毁资源
     */
    public void destroyVideo() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();  // 释放资源
            mediaPlayer = null;
        }
        surfaceHolder = null;
        playerSurfaceView = null;
        videoPosition = 0;
        removeAllListener();
        destroyTimeTask();
        myHandler.removeCallbacksAndMessages(null);
    }


    //--------------------------------------------------------------------------------------
    // ######## 广播相关 ########
    //--------------------------------------------------------------------------------------

    public class NetChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (onNetChangeListener == null) {
                return;
            }
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
            if (netInfo != null && netInfo.isAvailable()) {
                if (netInfo.getType() == ConnectivityManager.TYPE_WIFI) { //WiFi网络
                    onNetChangeListener.onWifi(mediaPlayer);
                } else if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) {   //3g网络
                    onNetChangeListener.onMobile(mediaPlayer);
                } else {    //其他
                    Log.i(TAG, "其他网络");
                }
            } else {
                onNetChangeListener.onNoAvailable(mediaPlayer);
            }
        }
    }

    //--------------------------------------------------------------------------------------
    // ######## 自定义回调 ########
    //--------------------------------------------------------------------------------------

    private void removeAllListener() {
        if (onNetChangeListener != null) {
            onNetChangeListener = null;
        }
        if (onPlayerCreatedListener != null) {
            onPlayerCreatedListener = null;
        }
    }


    //网络监听回调
    private OnNetChangeListener onNetChangeListener;

    public void setOnNetChangeListener(OnNetChangeListener onNetChangeListener) {
        this.onNetChangeListener = onNetChangeListener;
    }

    public interface OnNetChangeListener {
        //wifi
        void onWifi(MediaPlayer mediaPlayer);

        //手机
        void onMobile(MediaPlayer mediaPlayer);

        //不可用
        void onNoAvailable(MediaPlayer mediaPlayer);
    }

    //  SurfaceView初始化完成回调
    private OnPlayerCreatedListener onPlayerCreatedListener;

    public void setOnPlayerCreatedListener(OnPlayerCreatedListener onPlayerCreatedListener) {
        this.onPlayerCreatedListener = onPlayerCreatedListener;
    }

    public interface OnPlayerCreatedListener {
        //  不可用
        void onPlayerCreated(String url, String title);
    }

    //-----------------------播放完回调
    private OnCompletionListener onCompletionListener;

    public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
        this.onCompletionListener = onCompletionListener;
    }

    public interface OnCompletionListener {
        void onCompletion(MediaPlayer mediaPlayer);
    }

}